package com.ext.aic.apis.attachment;

import android.content.Context;

import com.ext.aic.beans.PreUploadInfo;
import com.eyinfo.android_pure_utils.HandlerManager;
import com.eyinfo.android_pure_utils.events.RunnableParamsN;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.cert.X509Certificate;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class ObsUploadRequest {

    protected void onUploadProgress(PreUploadInfo uploadInfo, int percent) {

    }

    protected void onUploadFailure(PreUploadInfo uploadInfo, String message) {

    }

    protected void onUploadSuccess(PreUploadInfo uploadInfo) {

    }

    private String getMimeType(String fileName) {
        String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
        switch (extension) {
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            default:
                return "application/octet-stream";
        }
    }

//    public void upload(Context context, PreUploadInfo uploadInfo, File file) {
//        ProgressRequestBody fileBody = new ProgressRequestBody(file, null, (bytesWritten, totalBytes) -> {
//            int percent = (int) ((bytesWritten * 100) / totalBytes);
//            onUploadProgress(uploadInfo, percent);
//        });
//        HttpUrl rawUrl = HttpUrl.parse(uploadInfo.getUrl()).newBuilder()
//                .addEncodedQueryParameter("AccessKeyId", uploadInfo.getAccessKeyId())
//                .addEncodedQueryParameter("Expires", uploadInfo.getExpires())
//                .addEncodedQueryParameter("Signature", uploadInfo.getSignature())
//                .build();
//
//        Request.Builder builder = new Request.Builder()
//                .url(rawUrl)
//                .put(fileBody)
//                .header("x-obs-acl", "private")
//                .removeHeader("Content-Type");
//
//        Predicate<Response> customRetryCondition = response -> {
//            int code = response.code();
//            return (code >= 500 && code < 600) || code == 429 || code == 403;
//        };
//        OkHttpClient client = new OkHttpClient.Builder()
//                .retryOnConnectionFailure(true)
//                .addInterceptor(new RetryInterceptor(3, customRetryCondition))
//                .connectTimeout(5000, TimeUnit.MILLISECONDS)
//                .readTimeout(30000, TimeUnit.MILLISECONDS)
//                .writeTimeout(30000, TimeUnit.MILLISECONDS)
//                .protocols(Collections.singletonList(Protocol.HTTP_1_1))
//                .build();
//        client.newCall(builder.build()).enqueue(new Callback() {
//            @Override
//            public void onFailure(Call call, IOException e) {
//                onUploadFailure(uploadInfo, e.getMessage());
//            }
//
//            @Override
//            public void onResponse(Call call, Response response) throws IOException {
//                if (response.isSuccessful()) {
//                    onUploadProgress(uploadInfo, 100);
//                    onUploadSuccess(uploadInfo);
//                } else {
//                    onUploadFailure(uploadInfo, "HTTP " + response.code() + ": " + response.body().string());
//                }
//            }
//        });
//    }

    private String readErrorStream(HttpURLConnection connection) {
        try {
            InputStream errorStream = connection.getErrorStream();
            if (errorStream != null) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                return response.toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    public void upload(Context context, PreUploadInfo uploadInfo, File file) {
        new Thread(() -> {
            HttpURLConnection connection = null;
            try {
                URL url = new URL(uploadInfo.getUrl());
                String query = String.format(
                        "AccessKeyId=%s&Expires=%s&Signature=%s",
                        URLEncoder.encode(uploadInfo.getAccessKeyId(), "UTF-8"),
                        URLEncoder.encode(uploadInfo.getExpires(), "UTF-8"),
                        URLEncoder.encode(uploadInfo.getSignature(), "UTF-8")
                );
                URL fullUrl = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile() + "?" + query);

                connection = (HttpURLConnection) fullUrl.openConnection();
                if (connection instanceof HttpsURLConnection) {
                    HttpsURLConnection httpsConn = (HttpsURLConnection) connection;

                    TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() {
                        public void checkClientTrusted(X509Certificate[] chain, String authType) {}
                        public void checkServerTrusted(X509Certificate[] chain, String authType) {}
                        public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
                    }};
                    SSLContext sslContext = SSLContext.getInstance("SSL");
                    sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
                    httpsConn.setSSLSocketFactory(sslContext.getSocketFactory());
                    httpsConn.setHostnameVerifier((hostname, session) -> true);
                }

                connection.setRequestMethod("PUT");
                connection.setDoOutput(true);

                connection.setConnectTimeout(30000);
                connection.setReadTimeout(30000);

                connection.setRequestProperty("x-obs-acl", "private");
                connection.setRequestProperty("Content-Type", ""); // 移除默认 Content-Type

                OutputStream outputStream = new BufferedOutputStream(connection.getOutputStream());
                FileInputStream inputStream = new FileInputStream(file);

                byte[] buffer = new byte[4096];
                long totalBytes = file.length();
                long uploadedBytes = 0;
                int bytesRead;

                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                    uploadedBytes += bytesRead;

                    int percent = (int) ((uploadedBytes * 100) / totalBytes);
                    HandlerManager.getInstance().post(new RunnableParamsN<Object>() {
                        @Override
                        public void run(Object... objects) {
                            onUploadProgress(uploadInfo, percent);
                        }
                    });
                }

                outputStream.flush();
                outputStream.close();
                inputStream.close();

                int retryCount = 0;
                int maxRetries = 3;
                boolean shouldRetry;

                do {
                    shouldRetry = false;
                    int responseCode = connection.getResponseCode();

                    if (responseCode >= 200 && responseCode < 300) {
                        HandlerManager.getInstance().post(new RunnableParamsN<Object>() {
                            @Override
                            public void run(Object... objects) {
                                onUploadProgress(uploadInfo, 100);
                                onUploadSuccess(uploadInfo);
                            }
                        });
                    } else {
                        if ((responseCode >= 500 && responseCode < 600) ||
                                responseCode == 429 ||
                                responseCode == 403) {

                            if (retryCount++ < maxRetries) {
                                shouldRetry = true;
                                connection.disconnect();
                                connection = (HttpURLConnection) fullUrl.openConnection();
                                continue;
                            }
                        }

                        String error = "HTTP " + responseCode + ": " + readErrorStream(connection);
                        HandlerManager.getInstance().post(new RunnableParamsN<Object>() {
                            @Override
                            public void run(Object... objects) {
                                onUploadFailure(uploadInfo, error);
                            }
                        });
                    }
                } while (shouldRetry);

            } catch (Exception e) {
                HandlerManager.getInstance().post(new RunnableParamsN<Object>() {
                    @Override
                    public void run(Object... objects) {
                        onUploadFailure(uploadInfo, e.getMessage());
                    }
                });
            }
        }).start();
    }
}
